+/*
+ Serial interface - POSIX layer.
+
+ Copyright (C) 2006 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#include "gbser.h"
+#include <assert.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define MYMAGIC 0x91827364
+typedef struct {
+ struct termios orig_tio;
+ struct termios my_tio;
+ FILE *fh;
+ int fd;
+ unsigned long magic;
+} gbser_posix_handle;
+
+static
+speed_t
+mkspeed(unsigned br)
+{
+ switch (br) {
+ case 1200: return B1200;
+ case 2400: return B2400;
+ case 4800: return B4800;
+ case 9600: return B9600;
+ case 19200: return B19200;
+#if defined B57600
+ case 57600: return B57600;
+#endif
+#if defined B115200
+ case 115200: return B115200;
+#endif
+ default: return B4800;
+ }
+}
+
+/*
+gbser_istty(void *handle)
+{
+ gbser_posix_handle *h = (gbser_posix_handle *) handle;
+ assert(h->magic == MYMAGIC);
+
+ return isatty(h->fd);
+}
+*/
+
+void *
+gbser_init(const char *name)
+{
+ gbser_posix_handle *h;
+
+ h = xcalloc(sizeof *h, 1);
+ h->magic = MYMAGIC;
+
+ h->fh = xfopen(name, "rb", "serial layer");
+ h->fd = fileno(h->fh);
+// h->fd = open(name, O_RDWR | O_EXCL | O_SYNC);
+
+ if (!isatty(h->fd)) {
+ goto open_fail;
+ }
+
+ tcgetattr(h->fd, &h->orig_tio);
+
+ h->my_tio = h->orig_tio;
+ h->my_tio.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|
+ IGNCR|IGNCR|IXON);
+ h->my_tio.c_cflag &= ~(CSIZE|PARENB);
+ h->my_tio.c_cflag |= CS8;
+ h->my_tio.c_oflag = 0;
+ h->my_tio.c_lflag = 0;
+ h->my_tio.c_iflag = 0;
+ h->my_tio.c_cc[VTIME] = 10; /* Time out after one second */
+ h->my_tio.c_cc[VMIN] = 255;
+
+ return h;
+
+open_fail:
+ if (h->fh) {
+ fclose(h->fh);
+ }
+ xfree(h);
+ return NULL;
+}
+
+void
+gbser_deinit(void *handle)
+{
+ gbser_posix_handle *h = (gbser_posix_handle *) handle;
+ assert(h->magic == MYMAGIC);
+
+ tcsetattr(h->fd, TCSAFLUSH, &h->orig_tio);
+ fclose(h->fh);
+ xfree(handle);
+}
+
+int
+gbser_setspeed(void *handle, unsigned speed)
+{
+ speed_t s;
+ gbser_posix_handle *h = (gbser_posix_handle *) handle;
+ assert(h->magic == MYMAGIC);
+
+ s = mkspeed(speed);
+
+ cfsetospeed(&h->my_tio, s);
+ cfsetispeed(&h->my_tio, s);
+
+ return !tcsetattr(h->fd, TCSAFLUSH, &h->my_tio);
+}
+
+int
+gbser_read(void *handle, char *ibuf, int size)
+{
+ int n;
+ char *c;
+ char tbuf[256];
+ char *tp = tbuf;
+ibuf[0] = 0;
+ gbser_posix_handle *h = (gbser_posix_handle *) handle;
+ assert(h->magic == MYMAGIC);
+
+// n = read(h->fd, ibuf, size);
+// printf("Returning %d\n", n);
+redo:
+ fgets(ibuf, size, h->fh);
+// rtrim(ibuf);
+if (strlen(ibuf) == 0)
+ goto redo;
+ return 1;
+}
+/*
+ Serial interface - Windows layer.
+
+ Copyright (C) 2006 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#include "gbser.h"
+#include <windows.h>
+#include <setupapi.h>
+
+typedef struct gbser_win_handle {
+ HANDLE comport;
+} gbser_win_handle;
+
+#define xCloseHandle(a) if (a) { CloseHandle(a); } a = NULL;
+
+void *
+gbser_init(const char *portname)
+{
+// DCB tio;
+ COMMTIMEOUTS timeout;
+ HANDLE comport;
+ char *xname= xstrdup("\\\\.\\\\");
+ gbser_win_handle* handle = xcalloc(1, sizeof(*handle));;
+
+ /* Amazingly, windows will fail the open below unless we
+ * prepend \\.\ to the name. It also then fails the open
+ * unless we strip the colon from the name. Aaaaargh!
+ */
+ xname = xstrappend(xname, portname);
+ if (xname[strlen(xname)-1] == ':')
+ xname[strlen(xname)-1] = 0;
+// xCloseHandle(comport);
+
+ comport = CreateFile(xname, GENERIC_READ|GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (comport == INVALID_HANDLE_VALUE) {
+ return NULL;
+ }
+ handle->comport = comport;
+
+#if 0
+ tio.DCBlength = sizeof(DCB);
+ GetCommState (comport, &tio);
+// tio.BaudRate = mkspeed(bitrate);
+ {
+ extern int mkspeed(int);
+ tio.BaudRate = mkspeed(4800);
+ }
+ tio.fBinary = TRUE;
+ tio.fParity = TRUE;
+ tio.fOutxCtsFlow = FALSE;
+ tio.fOutxDsrFlow = FALSE;
+ tio.fDtrControl = DTR_CONTROL_ENABLE;
+ tio.fDsrSensitivity = FALSE;
+ tio.fTXContinueOnXoff = TRUE;
+ tio.fOutX = FALSE;
+ tio.fInX = FALSE;
+ tio.fErrorChar = FALSE;
+ tio.fNull = FALSE;
+ tio.fRtsControl = RTS_CONTROL_ENABLE;
+ tio.fAbortOnError = FALSE;
+ tio.ByteSize = 8;
+ tio.Parity = NOPARITY;
+ tio.StopBits = ONESTOPBIT;
+
+ if (!SetCommState (comport, &tio)) {
+ /*
+ * Probably not a com port. Let caller try it as a file.
+ */
+
+ return NULL;
+ }
+#else
+ gbser_setspeed(handle, 4800);
+#endif
+
+ GetCommTimeouts (comport, &timeout);
+ /* We basically do single character reads and simulate line input
+ * mode, so these values are kind of fictional.
+ */
+ timeout.ReadIntervalTimeout = 1000;
+ timeout.ReadTotalTimeoutMultiplier = 1000;
+ timeout.ReadTotalTimeoutConstant = 1000;
+ timeout.WriteTotalTimeoutMultiplier = 1000;
+ timeout.WriteTotalTimeoutConstant = 1000;
+ if (!SetCommTimeouts (comport, &timeout)) {
+ xCloseHandle (comport);
+ fatal("SetCommTimeouts failed.\n");
+ }
+ return handle;
+}
+
+/*
+ * Returns 1 on success, 0 on errro.
+ */
+int
+gbser_setspeed(void *handle, unsigned speed)
+{
+ extern int mkspeed(int); /* From magproto.c */
+ gbser_win_handle *h = (gbser_win_handle *) handle;
+ DCB tio;
+
+ tio.DCBlength = sizeof(DCB);
+ GetCommState(h->comport, &tio);
+
+ tio.BaudRate = mkspeed(speed);
+ tio.fBinary = TRUE;
+ tio.fParity = TRUE;
+ tio.fOutxCtsFlow = FALSE;
+ tio.fOutxDsrFlow = FALSE;
+ tio.fDtrControl = DTR_CONTROL_ENABLE;
+ tio.fDsrSensitivity = FALSE;
+ tio.fTXContinueOnXoff = TRUE;
+ tio.fOutX = FALSE;
+ tio.fInX = FALSE;
+ tio.fErrorChar = FALSE;
+ tio.fNull = FALSE;
+ tio.fRtsControl = RTS_CONTROL_ENABLE;
+ tio.fAbortOnError = FALSE;
+ tio.ByteSize = 8;
+ tio.Parity = NOPARITY;
+ tio.StopBits = ONESTOPBIT;
+
+ if (!SetCommState (h->comport, &tio)) {
+ /*
+ * Probably not a com port. Let caller try it as a file.
+ */
+
+ return 0;
+ }
+ return 1;
+}
+
+int
+gbser_read(void *handle, char *ibuf, int size)
+{
+ gbser_win_handle *h = (gbser_win_handle *) handle;
+ int i = 0;
+ DWORD cnt;
+
+ ibuf[0]='0';
+ for(;i < size;i++) {
+ if (ReadFile (h->comport, &ibuf[i], 1, &cnt, NULL) != TRUE)
+ break;
+ if (cnt < 1)
+ return 0;
+ if (ibuf[i] == '\n')
+ break;
+ }
+
+ ibuf[i] = 0;
+ return 1;
+}
+
+void
+gbser_deinit(void *handle)
+{
+ gbser_win_handle *h = (gbser_win_handle *) handle;
+ xfree(h);
+}